home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / DOSKBD.C < prev    next >
C/C++ Source or Header  |  1992-06-04  |  34KB  |  1,374 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/doskbd.c,v 1.7 1992/06/04 12:40:40 jinx Exp $
  4.  
  5. Copyright (c) 1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. /* These flags determine how the code will behave. */
  36.  
  37. #define DOSX_USE_INT_INTERCEPT
  38. #define DOSX_RM_HANDLER_UNTOUCHED
  39. #define DOSX_PM_HANDLER_UNTOUCHED
  40. /* #define DOSX_RM_HANDLER_REAL */
  41. #define DPMI_RM_HANDLER_REAL
  42. #define DPMI_PM_HANDLER_UNTOUCHED
  43.  
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <errno.h>
  47. #include <bios.h>
  48. #include <dos.h>
  49. #include <int.h>
  50. #include "msdos.h"
  51.  
  52. #ifdef getDS
  53. #undef getDS
  54. #endif
  55.  
  56. #include "dossys.h"
  57. #include "dosinsn.h"
  58. #include "doskbd.h"
  59.  
  60. #ifndef ELOOP
  61. #  define ELOOP 2000
  62. #endif
  63.  
  64. #ifndef EFAULT
  65. #  define EFAULT 2001
  66. #endif
  67.  
  68. /* Tables mapping scan codes to ASCII characters.
  69.    Entries with NULL (\0) should not be mapped by the
  70.    Scheme keyboard ISR.  Let the default handler map them.
  71.  */
  72.  
  73. static unsigned char
  74. shifted_scan_code_to_ascii[] =
  75.     '\0',        /* 0 */
  76.     '\033',        /* 1 */
  77.     '!',        /* 2 */
  78.     '@',        /* 3 */
  79.     '#',        /* 4 */
  80.     '$',        /* 5 */
  81.     '%',        /* 6 */
  82.     '^',        /* 7 */
  83.     '&',        /* 8 */
  84.     '*',        /* 9 */
  85.     '(',        /* 10 */
  86.     ')',        /* 11 */
  87.     '_',        /* 12 */
  88.     '+',        /* 13 */
  89.     '\177',        /* 14 */
  90.     '\t',        /* 15 */
  91.     'Q',        /* 16 */
  92.     'W',        /* 17 */
  93.     'E',        /* 18 */
  94.     'R',        /* 19 */
  95.     'T',        /* 20 */
  96.     'Y',        /* 21 */
  97.     'U',        /* 22 */
  98.     'I',        /* 23 */
  99.     'O',        /* 24 */
  100.     'P',        /* 25 */
  101.     '{',        /* 26 */
  102.     '}',        /* 27 */
  103.     '\r',        /* 28 */
  104.     '\0',        /* 29 */
  105.     'A',        /* 30 */
  106.     'S',        /* 31 */
  107.     'D',        /* 32 */
  108.     'F',        /* 33 */
  109.     'G',        /* 34 */
  110.     'H',        /* 35 */
  111.     'J',        /* 36 */
  112.     'K',        /* 37 */
  113.     'L',        /* 38 */
  114.     ':',        /* 39 */
  115.     '\"',        /* 40 */
  116.     '~',        /* 41 */
  117.     '\0',        /* 42 */
  118.     '|',        /* 43 */
  119.     'Z',        /* 44 */
  120.     'X',        /* 45 */
  121.     'C',        /* 46 */
  122.     'V',        /* 47 */
  123.     'B',        /* 48 */
  124.     'N',        /* 49 */
  125.     'M',        /* 50 */
  126.     '<',        /* 51 */
  127.     '>',        /* 52 */
  128.     '?',        /* 53 */
  129.     '\0',        /* 54 */
  130.     '\0',        /* 55 */
  131.     '\0',        /* 56 */
  132.     ' '        /* 57 */
  133.   };
  134.     
  135. static unsigned char
  136. unshifted_scan_code_to_ascii[] =
  137. {
  138.     '\0',        /* 0 */
  139.     '\033',        /* 1 */
  140.     '1',        /* 2 */
  141.     '2',        /* 3 */
  142.     '3',        /* 4 */
  143.     '4',        /* 5 */
  144.     '5',        /* 6 */
  145.     '6',        /* 7 */
  146.     '7',        /* 8 */
  147.     '8',        /* 9 */
  148.     '9',        /* 10 */
  149.     '0',        /* 11 */
  150.     '-',        /* 12 */
  151.     '=',        /* 13 */
  152.     '\177',        /* 14 */
  153.     '\t',        /* 15 */
  154.     'q',        /* 16 */
  155.     'w',        /* 17 */
  156.     'e',        /* 18 */
  157.     'r',        /* 19 */
  158.     't',        /* 20 */
  159.     'y',        /* 21 */
  160.     'u',        /* 22 */
  161.     'i',        /* 23 */
  162.     'o',        /* 24 */
  163.     'p',        /* 25 */
  164.     '[',        /* 26 */
  165.     ']',        /* 27 */
  166.     '\r',        /* 28 */
  167.     '\0',        /* 29 */
  168.     'a',        /* 30 */
  169.     's',        /* 31 */
  170.     'd',        /* 32 */
  171.     'f',        /* 33 */
  172.     'g',        /* 34 */
  173.     'h',        /* 35 */
  174.     'j',        /* 36 */
  175.     'k',        /* 37 */
  176.     'l',        /* 38 */
  177.     ';',        /* 39 */
  178.     '\'',        /* 40 */
  179.     '`',        /* 41 */
  180.     '\0',        /* 42 */
  181.     '\\',        /* 43 */
  182.     'z',        /* 44 */
  183.     'x',        /* 45 */
  184.     'c',        /* 46 */
  185.     'v',        /* 47 */
  186.     'b',        /* 48 */
  187.     'n',        /* 49 */
  188.     'm',        /* 50 */
  189.     ',',        /* 51 */
  190.     '.',        /* 52 */
  191.     '/',        /* 53 */
  192.     '\0',        /* 54 */
  193.     '\0',        /* 55 */
  194.     '\0',        /* 56 */
  195.     ' '        /* 57 */
  196.   };
  197.  
  198. static unsigned char modifier_mask = 0x4f;
  199.  
  200. union RM_address
  201. {
  202.   unsigned fp;
  203.   struct
  204.     {
  205.       unsigned short off;
  206.       unsigned short seg;
  207.     } x;
  208. };
  209.  
  210. dos_boolean
  211. under_QEMM_386_p (void)
  212. {
  213.   unsigned int i;
  214.   union REGS iregs, oregs;
  215.  
  216.   iregs.h.al = 0x01;
  217.   iregs.x.bx = 0x5145;
  218.   iregs.x.cx = 0x4d4d;
  219.   iregs.x.dx = 0x3432;
  220.  
  221.   for (i = 0xc0; i <= 0xff; i++)
  222.   {
  223.     iregs.h.ah = i;
  224.     int86 (0x2f, &iregs, &oregs);
  225.     if (oregs.x.bx == 0x4f4b)
  226.       return (dos_true);
  227.   }
  228.   return (dos_false);
  229. }
  230.  
  231. dos_boolean
  232. under_DPMI_p (void)
  233. {
  234.   union REGS regs;
  235.   
  236.   regs.e.eax = 0x1686;
  237.   int86 (0x2f, ®s, ®s);
  238.   return (regs.x.ax == 0);
  239. }
  240.  
  241. static void
  242. normalize_RM_address (union RM_address * addr)
  243. {
  244.   if (addr->x.off > 0xf)
  245.   {
  246.     addr->x.seg += (addr->x.off >> 4);
  247.     addr->x.off = (addr->x.off & 0xf);
  248.   }
  249.   return;
  250. }
  251.  
  252. static dos_boolean
  253. install_kbd_hook_p (char * var_name)
  254. {
  255.   extern int strcmp_ci (char *, char *);
  256.   char * envvar = (DOS_getenv (var_name));
  257.  
  258.   if ((envvar != NULL) && ((strcmp_ci (envvar, "true")) == 0))
  259.     return (dos_true);
  260.   else
  261.     return (dos_false);
  262. }
  263.  
  264. /*
  265.    We would like to use Zortech's int_intercept with the following
  266.    routine under DOSX (or Phar Lap).
  267.  
  268.    Unfortunately, it does not work under QEMM386 or under MS Windows 3.1.
  269.    The real-mode call-back routine is apparently just plain broken.
  270.  
  271.    In addition, bypassing DOSX under DPMI 0.9 and using DPMI's
  272.    real-mode call backs does not work consistently, and the keyboard
  273.    interrupt happens only in real mode since we are capturing the
  274.    interrupt DOS uses to tell the BIOS that a scan code has arrived
  275.    after doing the handshake with the keyboard device itself.
  276.  
  277.    Thus, under DPMI, we install our own hard-coded real-mode keyboard
  278.    driver and don't bother with a protected mode handler.  All the
  279.    code is here in case it can be turned on in the future, perhaps for
  280.    a different DOS Extender or a new version of DPMI.
  281.  
  282.    Apparently telling DOSX to install a protected mode handler and
  283.    making it reflect real mode interrupts to protected mode does not
  284.    work consistently under QEMM386 either, thus we are now installing
  285.    a real-mode handler no matter what, although using different
  286.    mechanisms under DPMI and not DPMI.
  287.  */
  288.  
  289. #ifdef DOSX_USE_INT_INTERCEPT
  290.  
  291. #define PC_KBD_ALT_MASK            0x8
  292. #define PC_KBD_CTRL_MASK        0x4
  293. #define PC_KBD_SHIFT_MASK        0x3
  294. #define PC_KBD_CAPSL_MASK        0x40
  295.  
  296. #define DOS_HOOK_TRANSLATE_KEYSTROKE    0x4f
  297. #define DOS_KBD_FUNC_RECORD_KEYSTROKE    0x5
  298.  
  299. int
  300. bios_keyboard_handler(struct INT_DATA *pd)
  301. {
  302.   unsigned char scan_code, chord, ascii;
  303.   union REGS regs;
  304.  
  305.   if (pd->regs.h.ah != DOS_HOOK_TRANSLATE_KEYSTROKE)
  306.     return (INTERRUPT_CHAIN_NEXT);
  307.  
  308.   scan_code = (pd->regs.h.al);
  309.   if (scan_code >= (sizeof (shifted_scan_code_to_ascii)))
  310.     return (INTERRUPT_CHAIN_NEXT);
  311.  
  312.   chord = ((bioskey (_KEYBRD_SHIFTSTATUS)) & modifier_mask);
  313.  
  314.   if ((chord == 0) || (chord == PC_KBD_ALT_MASK))
  315.     ascii = ((int) unshifted_scan_code_to_ascii[scan_code]);
  316.   else
  317.     ascii = ((int) shifted_scan_code_to_ascii[scan_code]);
  318.  
  319.   if (ascii == 0)
  320.     return (INTERRUPT_CHAIN_NEXT);
  321.   if ((chord & PC_KBD_CTRL_MASK) != 0)
  322.     ascii &= ~0x60;            /* Controlify */
  323.   if (chord & PC_KBD_ALT_MASK)
  324.     ascii |= 0x80;            /* Metafy */
  325.   if (ascii == 0360)
  326.     return (INTERRUPT_CHAIN_NEXT);    /* Problems with M-p */
  327.   if ((ascii == 0200) || (ascii == 0))
  328.     scan_code = 3;            /* Problems with C-Space */
  329.  
  330.   /* Insert metafied char in bios buffer. */
  331.   regs.h.ah = DOS_KBD_FUNC_RECORD_KEYSTROKE;
  332.   regs.h.ch = scan_code;
  333.   regs.h.cl = ascii;
  334.   int86 (DOS_INTVECT_KEYBOARD_REQUEST, ®s, ®s);
  335.  
  336.   pd->regs.e.flags &= ~1;        /* clear CF, scan code ignored! */
  337.   return (INTERRUPT_RETURN);
  338. }
  339. #endif /* DOSX_USE_INT_INTERCEPT */
  340.  
  341. static void
  342. DPMI_PM_getvector (unsigned vecnum, unsigned * eip, unsigned * cs)
  343. {
  344.   union REGS regs;
  345.   
  346.   regs.x.ax = 0x204;
  347.   regs.h.bl = (vecnum & 0xff);
  348.   int86 (0x31, ®s, ®s);
  349.   * eip = regs.e.edx;
  350.   * cs = ((unsigned) regs.x.cx);
  351.   return;
  352. }
  353.  
  354. static int
  355. DPMI_PM_setvector (unsigned vecnum, unsigned eip, unsigned cs)
  356. {
  357.   union REGS regs;
  358.   
  359.   regs.x.ax = 0x205;
  360.   regs.h.bl = (vecnum & 0xff);
  361.   regs.e.edx = eip;
  362.   regs.x.cx = ((unsigned short) cs);
  363.   int86 (0x31, ®s, ®s);
  364.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  365. }
  366.  
  367. static void
  368. DPMI_RM_getvector (unsigned vecnum, unsigned short * ip, unsigned short * cs)
  369. {
  370.   union REGS regs;
  371.   
  372.   regs.x.ax = 0x200;
  373.   regs.h.bl = (vecnum & 0xff);
  374.   int86 (0x31, ®s, ®s);
  375.   * ip = regs.x.dx;
  376.   * cs = regs.x.cx;
  377.   return;
  378. }
  379.  
  380. static int
  381. DPMI_RM_setvector (unsigned vecnum, unsigned short ip, unsigned short cs)
  382. {
  383.   union REGS regs;
  384.   
  385.   regs.x.ax = 0x201;
  386.   regs.h.bl = (vecnum & 0xff);
  387.   regs.x.cx = cs;
  388.   regs.x.dx = ip;
  389.   int86 (0x31, ®s, ®s);
  390.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  391. }
  392.  
  393. #ifdef DPMI_RM_HANDLER_PROTECTED
  394.  
  395. struct DPMI_RM_REGS
  396. {
  397.   unsigned long edi;        /* 0 */
  398.   unsigned long esi;        /* 4 */
  399.   unsigned long ebp;        /* 8 */
  400.   unsigned long esp;        /* 12 */
  401.   unsigned long ebx;        /* 16 */
  402.   unsigned long edx;        /* 20 */
  403.   unsigned long ecx;        /* 24 */
  404.   unsigned long eax;        /* 28 */
  405.   unsigned short flags;        /* 30 */
  406.   unsigned short es;        /* 32 */
  407.   unsigned short ds;        /* 34 */
  408.   unsigned short fs;        /* 36 */
  409.   unsigned short gs;        /* 38 */
  410.   unsigned short ip;        /* 40 */
  411.   unsigned short cs;        /* 42 */
  412.   unsigned short sp;        /* 44 */
  413.   unsigned short ss;        /* 48 */
  414.   unsigned short pad;        /* 50 */
  415.   unsigned long old_vector_ip;    /* 52 */
  416.   unsigned long old_vector_cs;    /* 56 */
  417. };
  418.  
  419. static int
  420. DPMI_allocate_RM_call_back (unsigned short * cb_ip,
  421.                 unsigned short * cb_cs,
  422.                 unsigned eip, unsigned cs,
  423.                 unsigned RM_regs, unsigned ds)
  424. {
  425.   union REGS regs;
  426.   struct SREGS sregs;
  427.   
  428.   segread (& sregs);
  429.   regs.x.ax = 0x303;
  430.   regs.e.esi = eip;
  431.   sregs.ds = cs;
  432.   regs.e.edi = RM_regs;
  433.   sregs.es = ds;
  434.  
  435.   int86x (0x31, ®s, ®s, &sregs);
  436.   * cb_ip = regs.x.dx;
  437.   * cb_cs = regs.x.cx;
  438.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  439. }
  440.  
  441. static int
  442. DPMI_free_RM_call_back (unsigned short cb_ip, unsigned short cb_cs)
  443. {
  444.   union REGS regs;
  445.   
  446.   regs.x.ax = 0x304;
  447.   regs.x.cx = cb_cs;
  448.   regs.x.dx = cb_ip;
  449.   int86 (0x31, ®s, ®s);
  450.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  451. }
  452.  
  453. #endif /* DPMI_RM_HANDLER_PROTECTED */
  454.  
  455. #ifdef DPMI_RM_HANDLER_REAL
  456.  
  457. static int
  458. DPMI_allocate_DOS_block (unsigned short size,
  459.              unsigned short * rm_seg,
  460.              unsigned short * pm_sel)
  461. {
  462.   union REGS regs;
  463.   
  464.   regs.x.ax = 0x100;
  465.   regs.x.bx = ((((unsigned) size) + 15) >> 4);    /* paragraphs */
  466.   int86 (0x31, & regs, & regs);
  467.   * rm_seg = regs.x.ax;
  468.   * pm_sel = regs.x.dx;
  469.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  470. }
  471.  
  472. static int
  473. DPMI_free_DOS_block (unsigned short selector)
  474. {
  475.   union REGS regs;
  476.   
  477.   regs.x.ax = 0x101;
  478.   regs.x.dx = selector;
  479.   int86 (0x31, & regs, & regs);
  480.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  481. }
  482.  
  483. #endif /* DPMI_RM_HANDLER_REAL */
  484.  
  485. #ifdef DOSX_RM_HANDLER_REAL
  486.  
  487. static int
  488. DOSX_allocate_DOS_block (unsigned short size,
  489.              unsigned short * rm_seg)
  490. {
  491.   union REGS regs;
  492. #if 0
  493.   
  494.   regs.x.ax = 0x25c0;
  495.   regs.x.bx = ((((unsigned) size) + 15) >> 4);    /* paragraphs */
  496.   int86 (0x21, & regs, & regs);
  497.   if ((regs.e.flags & 1) == 0)
  498.   {
  499.     * rm_seg = regs.x.ax;
  500.     return (DOS_SUCCESS);
  501.   }
  502.   if (regs.x.ax == 0x8)
  503.     errno = ENOMEM;
  504.   else
  505.     errno = EFAULT;
  506.   return (DOS_FAILURE);
  507.  
  508. #else /* not 0 */
  509.  
  510.   regs.h.ah = 0x48;
  511.   regs.x.bx = ((((unsigned) size) + 15) >> 4);    /* paragraphs */
  512.   int86 (0x21, & regs, & regs);
  513.   * rm_seg = regs.x.ax;
  514.   if ((regs.e.flags & 1) != 0)
  515.   {
  516.     errno = ENOMEM;
  517.     return (DOS_FAILURE);
  518.   }
  519.   return (DOS_SUCCESS);
  520.  
  521. #endif /* 0 */
  522. }
  523.  
  524. static int
  525. DOSX_free_DOS_block (unsigned short seg)
  526. {
  527.   union REGS regs;
  528. #if 0
  529.   
  530.   regs.x.ax = 0x25c1;
  531.   regs.x.cx = seg;
  532.   int86 (0x21, & regs, & regs);
  533.  
  534. #else /* not 0 */
  535.  
  536.   struct SREGS sregs;
  537.  
  538.   regs.h.ah = 0x49;
  539.   segread (&sregs);
  540.   sregs.es = seg;
  541.   int86x (0x21, & regs, & regs, & sregs);
  542.  
  543. #endif /* 0 */
  544.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  545. }
  546.  
  547. #endif /* DOSX_RM_HANDLER_REAL */
  548.  
  549. #ifndef DOSX_PM_HANDLER_UNTOUCHED
  550.  
  551. static void
  552. DOSX_PM_getvector (unsigned vecnum, unsigned * eip, unsigned * cs)
  553. {
  554.   union REGS regs;
  555.   struct SREGS sregs;
  556.   
  557.   regs.x.ax = 0x2502;
  558.   regs.h.cl = (vecnum & 0xff);
  559.   segread (&sregs);
  560.   int86x (0x21, ®s, ®s, &sregs);
  561.   * eip = regs.e.ebx;
  562.   * cs = ((unsigned) sregs.es);
  563.   return;
  564. }
  565.  
  566. static void
  567. DOSX_installvector (unsigned vecnum, unsigned eip, unsigned cs)
  568. {
  569.   union REGS regs;
  570.   struct SREGS sregs;
  571.   
  572.   regs.x.ax = 0x2506;
  573.   regs.h.cl = (vecnum & 0xff);
  574.   regs.e.edx = eip;
  575.   segread (&sregs);
  576.   sregs.ds = cs;
  577.   int86x (0x21, ®s, ®s, &sregs);
  578.   return;
  579. }
  580.  
  581. static void
  582. DOSX_restore_vector (unsigned vecnum, unsigned eip,
  583.              unsigned cs, unsigned rmode)
  584. {
  585.   union REGS regs;
  586.   struct SREGS sregs;
  587.   
  588.   segread (&sregs);
  589.   sregs.ds = cs;
  590.   regs.e.edx = eip;
  591.   regs.e.ebx = rmode;
  592.   regs.x.ax = 0x2507;
  593.   regs.h.cl = (vecnum & 0xff);
  594.   int86x (0x21, ®s, ®s, &sregs);
  595.   return;
  596. }
  597.  
  598. #endif /* DOSX_PM_HANDLER_UNTOUCHED */
  599.  
  600. #if (!(defined(DOSX_RM_HANDLER_UNTOUCHED) && defined(DOSX_PM_HANDLER_UNTOUCHED)))
  601.  
  602. static void
  603. DOSX_RM_getvector (unsigned vecnum, unsigned * vector)
  604. {
  605.   union REGS regs;
  606.  
  607.   regs.x.ax = 0x2503;
  608.   regs.h.cl = (vecnum & 0xff);
  609.   int86 (0x21, ®s, ®s);
  610.   * vector = regs.e.ebx;
  611.   return;
  612. }
  613.  
  614. #endif /* !(DOSX_RM_HANDLER_UNTOUCHED && DOSX_PM_HANDLER_UNTOUCHED) */
  615.  
  616. #ifndef DOSX_RM_HANDLER_UNTOUCHED
  617.  
  618. static int
  619. DOSX_RM_setvector (unsigned vecnum, unsigned rm_address)
  620. {
  621.   union REGS regs;
  622.   
  623.   regs.x.ax = 0x2505;
  624.   regs.h.cl = (vecnum & 0xff);
  625.   regs.e.ebx = rm_address;
  626.   int86 (0x31, ®s, ®s);
  627.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  628. }
  629.  
  630. #if 0
  631. static int
  632. DOSX_convert_PM_to_RM_address (unsigned short sel, unsigned offset,
  633.                    unsigned length, unsigned * rm_address)
  634. {
  635.   union REGS regs;
  636.   struct SREGS sregs;
  637.  
  638.   segread (&sregs);
  639.   sregs.es = sel;
  640.   regs.e.ebx = offset;
  641.   regs.e.ecx = length;
  642.   regs.e.eax = 0x250F;
  643.   int86x (0x21, ®s, ®s, &sregs);
  644.   * rm_address = regs.e.ecx;
  645.   return (((regs.e.flags & 1) == 0) ? DOS_SUCCESS : DOS_FAILURE);
  646. }
  647. #endif /* 0 */
  648.  
  649. #endif /* DOSX_RM_HANDLER_UNTOUCHED */
  650.  
  651. static unsigned 
  652.   old_PM_vector_eip, 
  653.   old_PM_vector_cs;
  654.  
  655. static union RM_address old_RM_vector;
  656.  
  657. static void
  658.   * scheme_PM_vector = ((void *) NULL),
  659.   * scheme_RM_vector = ((void *) NULL);
  660.  
  661. #if (!defined (DOSX_PM_HANDLER_UNTOUCHED)) || (!defined (DPMI_PM_HANDLER_UNTOUCHED))
  662. static void *
  663. make_PM_trampoline (void (* hook) (void))
  664. {
  665.   void * trampoline;
  666.   INSN_DECLS ();
  667.  
  668.   trampoline = (malloc (TRAMP_SIZE (6)));
  669.   if (trampoline != ((void *) NULL))
  670.   {
  671.     INIT_INSNS (trampoline);
  672.     PUSH_INSN (old_PM_vector_cs);
  673.     PUSH_INSN (old_PM_vector_eip);
  674.     PUSH_INSN (& modifier_mask);
  675.     PUSH_INSN (unshifted_scan_code_to_ascii);
  676.     PUSH_INSN (shifted_scan_code_to_ascii);
  677.     PUSH_INSN (getDS ());
  678.     JMP_INSN (hook);
  679.     HLT_INSNS (6);
  680.   }
  681.   return (trampoline);
  682. }
  683. #endif /* !DOSX_PM_HANDLER_UNTOUCHED || !DPMI_PM_HANDLER_UNTOUCHED */
  684.  
  685. #ifdef DPMI_RM_HANDLER_PROTECTED
  686. static void *
  687. make_RM_trampoline (void (* hook) (void))
  688. {
  689.   void * trampoline;
  690.   INSN_DECLS ();
  691.  
  692.   trampoline = (malloc (TRAMP_SIZE (6)));
  693.   if (trampoline != ((void *) NULL))
  694.   {
  695.     INIT_INSNS (trampoline);
  696.     PUSH_INSN (old_RM_vector.x.seg);
  697.     PUSH_INSN (old_RM_vector.x.off);
  698.     PUSH_INSN (& modifier_mask);
  699.     PUSH_INSN (unshifted_scan_code_to_ascii);
  700.     PUSH_INSN (shifted_scan_code_to_ascii);
  701.     PUSH_INSN (getDS ());
  702.     JMP_INSN (hook);
  703.     HLT_INSNS (6);
  704.   }
  705.   return (trampoline);
  706. }
  707. #endif /* DPMI_RM_HANDLER_PROTECTED */
  708.  
  709. #ifdef DPMI_RM_HANDLER_PROTECTED
  710.   static union RM_address DPMI_RM_call_back;
  711.   static void * DPMI_RM_regs = ((void *) NULL);
  712. #endif /* DPMI_RM_HANDLER_PROTECTED */
  713.  
  714. #ifdef DPMI_RM_HANDLER_REAL
  715.   static unsigned short DPMI_RM_selector = 0;
  716. #endif /* DPMI_RM_HANDLER_REAL */
  717.  
  718. static char * DPMI_env_var = "MITSCHEME_DPMI_EXT_KBD";
  719.  
  720. static int
  721. DPMI_restore_kbd_hook (void)
  722. {
  723.   if (!(install_kbd_hook_p (DPMI_env_var)))
  724.     return (DOS_FAILURE);
  725.  
  726. #ifdef DPMI_RM_HANDLER_REAL
  727.   if (DPMI_RM_selector != 0)
  728.   {
  729.     if (((DPMI_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  730.                  old_RM_vector.x.off,
  731.                  old_RM_vector.x.seg))
  732.      != DOS_SUCCESS)
  733.     || ((DPMI_free_DOS_block (DPMI_RM_selector)) != DOS_SUCCESS))
  734.     {
  735.       errno = EACCES;
  736.       return (DOS_FAILURE);
  737.     }
  738.     DPMI_RM_selector = 0;
  739.     free (scheme_RM_vector);
  740.     scheme_RM_vector = ((void *) NULL);
  741.   }
  742. #endif /* #ifdef DPMI_RM_HANDLER_REAL */
  743.  
  744. #ifdef DPMI_RM_HANDLER_PROTECTED
  745.   if (scheme_RM_vector != ((void *) NULL))
  746.   {
  747.     if (((DPMI_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  748.                  old_RM_vector.x.off,
  749.                  old_RM_vector.x.seg))
  750.      != DOS_SUCCESS)
  751.     || ((DPMI_free_RM_call_back (DPMI_RM_call_back.x.off,
  752.                      DPMI_RM_call_back.x.seg))
  753.         != DOS_SUCCESS))
  754.     {
  755.       errno = EACCES;
  756.       return (DOS_FAILURE);
  757.     }
  758.     free (DPMI_RM_regs);
  759.     free (scheme_RM_vector);
  760.     scheme_RM_vector = ((void *) NULL);
  761.   }
  762. #endif /* DPMI_RM_HANDLER_PROTECTED */
  763.  
  764. #ifndef DPMI_PM_HANDLER_UNTOUCHED
  765.   if (scheme_PM_vector != ((void *) NULL))
  766.   {
  767.     if ((DPMI_PM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  768.                 old_PM_vector_eip,
  769.                 old_PM_vector_cs))
  770.     != DOS_SUCCESS)
  771.     {
  772.       errno = EACCES;
  773.       return (DOS_FAILURE);
  774.     }
  775.     free (scheme_PM_vector);
  776.     scheme_PM_vector = ((void *) NULL);
  777.   }
  778. #endif /* DPMI_PM_HANDLER_UNTOUCHED */
  779.  
  780.   return (DOS_SUCCESS);
  781. }
  782.  
  783. #if defined(DPMI_RM_HANDLER_REAL) || defined(DOSX_RM_HANDLER_REAL)
  784.  
  785. unsigned char RM_handler_pattern[] =
  786. {
  787.             /*  chain:                    */
  788. 0x9d,            /* 0    popf                    */
  789. 0xea,0,0,0,0,        /* 1    jmpf    next_in_chain            */
  790.             /*  kbd_isr:                    */
  791. 0x9c,            /* 6    pushf                    */
  792. 0x80,0xfc,0x4f,        /* 7    cmp    ah,4fh                */
  793. 0x75,0xf4,        /* a    jne    chain                */
  794. 0x3c,0x39,        /* c    cmp    al,39h                */
  795. 0x77,0xf0,        /* e    ja    chain                */
  796. 0x53,            /* 10    push    bx    ; Preserve bx        */
  797. 0x50,            /* 11    push    ax    ; Preserve scan code    */
  798. 0xb4,2,            /* 12    mov    ah,2h                */
  799. 0xcd,0x16,        /* 14    int    16h    ; Get modifier bits    */
  800. 0x2e,0x22,6,0xf4,0,    /* 16    and    al,cs:modifier mask        */
  801. 0x5b,            /* 1b    pop    bx    ; Get scan code        */
  802. 0x53,            /* 1c    push    bx                */
  803. 0x81,0xe3,0x3f,0,    /* 1d    and    bx,3fh    ; Drop fncn        */
  804. 0x3c,8,            /* 21    cmp    al,8h    ; Only meta bit set?    */
  805. 0x74,0xb,        /* 23    je    do_unshifted            */
  806. 0x3c,0,            /* 25    cmp    al,0    ; No modifier bits set? */
  807. 0x74,7,            /* 27    je    do_unshifted            */
  808.             /*  do_shifted:                    */
  809. 0x2e,0x8a,0x9f,0x80,0,    /* 29    mov    bl,cs:shifted_table[bx]        */
  810. 0xeb,5,            /* 2e    jmp    merge                */
  811.             /*  do_unshifted:                */
  812. 0x2e,0x8a,0x9f,0xba,0,    /* 30    mov    bl,cs:unshifted_table[bx]    */
  813.             /*  merge:                    */
  814. 0x80,0xfb,0,        /* 35    cmp    bl,0    ; No translation?    */
  815. 0x74,0x37,        /* 38    je    abort_translation        */
  816. 0x0f,0xba,0xe0,2,    /* 3a    bt    al,2h    ; Control set?        */
  817. 0x73,3,            /* 3e    jnc    after_ctrl            */
  818. 0x80,0xe3,0x9f,        /* 40    and    bl,09fh ; controlify        */
  819.             /*  after_ctrl:                    */
  820. 0x0f,0xba,0xe0,3,    /* 43    bt    al,3h    ; Alt set?        */
  821. 0x73,3,            /* 47    jnc    after_meta            */
  822. 0x80,0xcb,0x80,        /* 49    or    bl,080h ; metify        */
  823.             /*  after_meta:                    */
  824. 0x80,0xfb,0xf0,        /* 4c   cmp    bl,0f0h ; M-p ?            */
  825. 0x74,0x20,        /* 4f    je    abort_translation        */
  826. 0x58,            /* 51    pop    ax                */
  827. 0x51,            /* 52    push    cx    ; Preserve cx        */
  828. 0x50,            /* 53    push    ax                */
  829. 0x8a,0xe8,        /* 54    mov    ch,al    ; Scan code        */
  830. 0x80,0xfb,0,        /* 56    cmp    bl,0    ; C-Space?        */
  831. 0x75,2,            /* 59   jne    after_ctrl_space        */
  832. 0xb5,3,            /* 5b    mov    ch,3    ; Fudge scan code    */
  833.             /*  after_ctrl_space:                */
  834. 0x8a,0xcb,        /* 5d    mov    cl,bl    ; ASCII value        */
  835. 0xb4,5,            /* 5f    mov    ah,05h    ; fcn. number        */
  836. 0xcd,0x16,        /* 61    int    16h    ; Record keystroke    */
  837. 0x58,            /* 63    pop    ax    ; Restore registers    */
  838. 0x59,            /* 64    pop    cx                */
  839. 0x5b,            /* 65    pop    bx                */
  840. 0x55,            /* 66    push    bp                */
  841. 0x8b,0xec,        /* 67    mov    bp,sp                */
  842. 0x80,0x66,8,0xfe,    /* 69    and    8[bp],0feh  ; clc iret's flags    */
  843. 0x5d,            /* 6d    pop    bp                */
  844. 0x9d,            /* 6e    popf                    */
  845. 0xf8,            /* 6f    clc                    */
  846. 0xcf,            /* 70    iret                    */
  847.             /*  abort_translation:                */
  848. 0x58,            /* 71    pop    ax                */
  849. 0x5b,            /* 72    pop    bx                */
  850. 0xeb,0x8b        /* 73    jmp    chain                */
  851.             /* 75    PAD                    */
  852. };
  853.  
  854. #define PATTERN_SIZE        0x75
  855. #define PADDED_PATTERN_SIZE    0x80
  856. #define PATTERN_CHAIN_OFFSET    2
  857. #define PATTERN_START_OFFSET    6
  858. #define RM_ISR_TABLE_SIZE    0x3a
  859. #define RM_ISR_TOTAL_SIZE                    \
  860.   (PADDED_PATTERN_SIZE + (2 * RM_ISR_TABLE_SIZE) + 1)
  861. #define RM_ISR_MASK_OFFSET    (RM_ISR_TOTAL_SIZE - 1)
  862.  
  863. static void *
  864. make_RM_handler (void)
  865. {
  866.   unsigned char * copy;
  867.   unsigned short * wordptr;
  868.  
  869.   if (((sizeof (RM_handler_pattern)) != PATTERN_SIZE)
  870.       || ((sizeof (shifted_scan_code_to_ascii)) != RM_ISR_TABLE_SIZE)
  871.       || ((sizeof (unshifted_scan_code_to_ascii)) != RM_ISR_TABLE_SIZE)
  872.       || (RM_ISR_MASK_OFFSET != 0xf4))
  873.   {
  874.     fprintf (stderr, "make_RM_handler: Inconsistent sizes!\n");
  875.     fprintf (stderr, "       PATTERN_SIZE = %d\n", PATTERN_SIZE);
  876.     fprintf (stderr, "and (sizeof (RM_handler_pattern)) = %d\n",
  877.          (sizeof (RM_handler_pattern)));
  878.     fprintf (stderr, "       RM_ISR_TABLE_SIZE = %d\n",
  879.          RM_ISR_TABLE_SIZE);
  880.  
  881.     fprintf (stderr, "and (sizeof (shifted_scan_code_to_ascii)) = %d\n",
  882.          (sizeof (shifted_scan_code_to_ascii)));
  883.     fprintf (stderr, "and (sizeof (unshifted_scan_code_to_ascii)) = %d\n",
  884.          (sizeof (unshifted_scan_code_to_ascii)));
  885.     fprintf (stderr, "       RM_ISR_MASK_OFFSET  = 0x%x <> 0xf4",
  886.          RM_ISR_MASK_OFFSET);
  887.     errno = EFAULT;
  888.     return ((void *) NULL);
  889.   }
  890.  
  891.   copy = ((unsigned char *) (malloc (RM_ISR_TOTAL_SIZE)));
  892.   if (copy == ((unsigned char *) NULL))
  893.     return ((void *) NULL);
  894.  
  895.   memcpy (copy, RM_handler_pattern, (sizeof (RM_handler_pattern)));
  896.   memcpy ((copy + PADDED_PATTERN_SIZE),
  897.       shifted_scan_code_to_ascii,
  898.       RM_ISR_TABLE_SIZE);
  899.   memcpy ((copy + PADDED_PATTERN_SIZE + RM_ISR_TABLE_SIZE),
  900.       unshifted_scan_code_to_ascii,
  901.       RM_ISR_TABLE_SIZE);
  902.  
  903.   wordptr = ((unsigned short *) (copy + PATTERN_CHAIN_OFFSET));
  904.   * wordptr++ = old_RM_vector.x.off;
  905.   * wordptr = old_RM_vector.x.seg;
  906.   * (copy + RM_ISR_MASK_OFFSET) = modifier_mask;
  907.  
  908.   return ((void *) copy);
  909. }
  910.  
  911. #endif /* DPMI_RM_HANDLER_REAL || DOSX_RM_HANDLER_REAL */
  912.  
  913. static int
  914. DPMI_install_kbd_hook (void)
  915. {
  916.   if (!(install_kbd_hook_p (DPMI_env_var)))
  917.     return (DOS_FAILURE);
  918.  
  919. #ifndef DPMI_PM_HANDLER_UNTOUCHED
  920.  
  921.   DPMI_PM_getvector (DOS_INTVECT_SYSTEM_SERVICES,
  922.              & old_PM_vector_eip,
  923.              & old_PM_vector_cs);
  924.  
  925.   {
  926.     extern void DPMI_PM_scheme_system_isr (void);
  927.     void * PM_trampoline;
  928.  
  929.     PM_trampoline = (make_PM_trampoline (DPMI_PM_scheme_system_isr));
  930.     if (PM_trampoline == ((void *) NULL))
  931.     {
  932.       errno = ENOMEM;
  933.       return (DOS_FAILURE);
  934.     }
  935.     if ((DPMI_PM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  936.                 ((unsigned) PM_trampoline),
  937.                 (getCS ())))
  938.     != DOS_SUCCESS)
  939.     {
  940.       errno = EACCES;
  941.       free (PM_trampoline);
  942.       return (DOS_FAILURE);
  943.     }
  944.     scheme_PM_vector = PM_trampoline;
  945.   }
  946.  
  947. #endif /* DPMI_PM_HANDLER_UNTOUCHED */
  948.  
  949. #ifndef DPMI_RM_HANDLER_UNTOUCHED
  950.  
  951.   DPMI_RM_getvector (DOS_INTVECT_SYSTEM_SERVICES,
  952.              & old_RM_vector.x.off,
  953.              & old_RM_vector.x.seg);
  954.  
  955. #  ifdef DPMI_RM_HANDLER_PROTECTED
  956.  
  957.   {
  958.     extern void DPMI_RM_scheme_system_isr (void);
  959.     struct DPMI_RM_REGS * RM_regs;
  960.     union RM_address RM_call_back;
  961.     void * RM_trampoline;
  962.  
  963.     RM_regs = ((struct DPMI_RM_REGS *)
  964.            (malloc (sizeof (struct DPMI_RM_REGS))));
  965.     if (RM_regs == ((struct DPMI_RM_REGS *) NULL))
  966.     {
  967.       DPMI_restore_kbd_hook ();
  968.       errno = ENOMEM;
  969.       return (DOS_FAILURE);
  970.     }
  971.  
  972.     RM_regs->ss = 0;
  973.     RM_regs->sp = 0;
  974.     RM_regs->old_vector_ip = (old_RM_vector.x.off);
  975.     RM_regs->old_vector_cs = (old_RM_vector.x.seg);
  976.  
  977.     RM_trampoline = (make_RM_trampoline (DPMI_RM_scheme_system_isr));
  978.     if (RM_trampoline == ((void *) NULL))
  979.     {
  980.       free (RM_regs);
  981.       DPMI_restore_kbd_hook ();
  982.       errno = ENOMEM;
  983.       return (DOS_FAILURE);
  984.     }
  985.  
  986.     if (((DPMI_allocate_RM_call_back (& RM_call_back.x.off,
  987.                       & RM_call_back.x.seg,
  988.                       ((unsigned) RM_trampoline),
  989.                       ((unsigned) (getCS ())),
  990.                       ((unsigned) RM_regs),
  991.                       ((unsigned) (getDS ()))))
  992.      != DOS_SUCCESS)
  993.     || ((DPMI_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  994.                 RM_call_back.x.off,
  995.                 RM_call_back.x.seg))
  996.         != DOS_SUCCESS))
  997.     {
  998.       free (RM_trampoline);
  999.       free (RM_regs);
  1000.       DPMI_restore_kbd_hook ();
  1001.       errno = EACCES;
  1002.       return (DOS_FAILURE);
  1003.     }
  1004.     scheme_RM_vector = RM_trampoline;
  1005.     DPMI_RM_regs = ((void *) RM_regs);
  1006.     DPMI_RM_call_back = RM_call_back;
  1007.   }
  1008.  
  1009. #  else  /* not DPMI_RM_HANDLER_PROTECTED = DPMI_RM_HANDLER_REAL */
  1010.  
  1011.   {
  1012.     void * RM_handler;
  1013.     unsigned short real_mode_segment;
  1014.     unsigned short prot_mode_selector;
  1015.  
  1016.     RM_handler = (make_RM_handler ());
  1017.     if (RM_handler == ((void *) NULL))
  1018.     {
  1019.       int saved_errno = errno;
  1020.  
  1021.       DPMI_restore_kbd_hook ();
  1022.       errno = saved_errno;
  1023.       return (DOS_FAILURE);
  1024.     }
  1025.  
  1026.     if ((DPMI_allocate_DOS_block (RM_ISR_TOTAL_SIZE,
  1027.                   & real_mode_segment,
  1028.                   & prot_mode_selector))
  1029.     != DOS_SUCCESS)
  1030.     {
  1031.       free (RM_handler);
  1032.       DPMI_restore_kbd_hook ();
  1033.       errno = ENOMEM;
  1034.       return (DOS_FAILURE);
  1035.     }
  1036.  
  1037.     farcpy (0, prot_mode_selector,
  1038.         ((unsigned) RM_handler), (getDS ()),
  1039.         RM_ISR_TOTAL_SIZE);
  1040.  
  1041.     if ((DPMI_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  1042.                 PATTERN_START_OFFSET,
  1043.                 real_mode_segment))
  1044.     != DOS_SUCCESS)
  1045.     {
  1046.       DPMI_free_DOS_block (prot_mode_selector);
  1047.       free (RM_handler);
  1048.       DPMI_restore_kbd_hook ();
  1049.       errno = EACCES;
  1050.       return (DOS_FAILURE);
  1051.     }
  1052.  
  1053.     DPMI_RM_selector = prot_mode_selector;
  1054.     scheme_RM_vector = RM_handler;        /* Kludge! */
  1055.   }
  1056.  
  1057. #  endif /* not DPMI_RM_HANDLER_PROTECTED */
  1058. #endif /* DPMI_RM_HANDLER_UNTOUCHED */
  1059.   return (DOS_SUCCESS);
  1060. }
  1061.  
  1062. #ifdef DOSX_RM_HANDLER_REAL
  1063.   static unsigned short DOSX_RM_segment = 0;
  1064. #endif /* DOSX_RM_HANDLER_REAL */
  1065. #ifdef DOSX_USE_INT_INTERCEPT
  1066.   static unsigned char kludge;
  1067. #endif /* DOSX_USE_INT_INTERCEPT */
  1068.  
  1069. static char * DOSX_env_var = "MITSCHEME_DOSX_EXT_KBD";
  1070.  
  1071. static int
  1072. DOSX_install_kbd_hook (void)
  1073. {
  1074.   if (!(install_kbd_hook_p (DOSX_env_var)))
  1075.     return (DOS_FAILURE);
  1076.   
  1077. #ifdef DOSX_USE_INT_INTERCEPT
  1078.   {
  1079.     int_intercept (DOS_INTVECT_SYSTEM_SERVICES, 
  1080.            bios_keyboard_handler, 
  1081.            256);
  1082.  
  1083.     scheme_PM_vector = ((void *) & kludge);
  1084.   }
  1085. #else /* not DOSX_USE_INT_INTERCEPT */
  1086. #ifndef DOSX_PM_HANDLER_UNTOUCHED
  1087.   {
  1088.     extern void DOSX_scheme_system_isr (void);
  1089.     void * trampoline;
  1090.  
  1091.     DOSX_PM_getvector (DOS_INTVECT_SYSTEM_SERVICES,
  1092.                & old_PM_vector_eip,
  1093.                & old_PM_vector_cs);
  1094.     DOSX_RM_getvector (DOS_INTVECT_SYSTEM_SERVICES,
  1095.                & old_RM_vector.fp);
  1096.  
  1097.     trampoline = (make_PM_trampoline (DOSX_scheme_system_isr));
  1098.     if (trampoline == ((void *) NULL))
  1099.       return (DOS_FAILURE);
  1100.  
  1101.     DOSX_installvector (DOS_INTVECT_SYSTEM_SERVICES,
  1102.             ((unsigned) trampoline),
  1103.             ((unsigned) (getCS ())));
  1104.  
  1105.     scheme_PM_vector = trampoline;
  1106.   }
  1107. #endif /* DOSX_PM_HANDLER_UNTOUCHED */
  1108.  
  1109. #ifdef DOSX_RM_HANDLER_REAL
  1110.   {
  1111.     void * RM_handler;
  1112.     union RM_address new_handler;
  1113.  
  1114.     DOSX_RM_getvector (DOS_INTVECT_SYSTEM_SERVICES,
  1115.                ((unsigned *) & old_RM_vector));
  1116.  
  1117.     RM_handler = (make_RM_handler ());
  1118.     if (RM_handler == ((void *) NULL))
  1119.       return (DOS_FAILURE);
  1120.  
  1121. #if 0
  1122.  
  1123.     if ((DOSX_convert_PM_to_RM_address ((getDS ()), ((unsigned) RM_handler),
  1124.                     RM_ISR_TOTAL_SIZE,
  1125.                     ((unsigned *) & new_handler)))
  1126.     != DOS_SUCCESS)
  1127.     {
  1128.       int saved_errno = errno;
  1129.  
  1130.       fflush (stdout);
  1131.       free (RM_handler);
  1132.       errno = saved_errno;
  1133.       return (DOS_FAILURE);
  1134.     }
  1135.     
  1136.     if ((new_handler.x.off & 0xf) != 0)
  1137.     {
  1138.       fflush (stdout);
  1139.       free (RM_handler);
  1140.       errno = EFAULT;
  1141.       return (DOS_FAILURE);
  1142.     }
  1143.  
  1144.     normalize_RM_address (& new_handler);
  1145.  
  1146.     if ((DOSX_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  1147.                 ((unsigned) new_handler)))
  1148.     != DOS_SUCCESS)
  1149.     {
  1150.       fflush (stdout);
  1151.       free (RM_handler);
  1152.       errno = EFAULT;
  1153.       return (DOS_FAILURE);
  1154.     }
  1155.  
  1156. #else /* not 0 */
  1157.     
  1158.     if ((DOSX_allocate_DOS_block (RM_ISR_TOTAL_SIZE, &new_handler.x.seg))
  1159.     != DOS_SUCCESS)
  1160.     {
  1161.       int saved_errno = errno;
  1162.  
  1163.       free (RM_handler);
  1164.       errno = saved_errno;
  1165.       return (DOS_FAILURE);
  1166.     }
  1167.     new_handler.x.off = 0;
  1168.  
  1169.     /* This assumes that the bottom 1 Mb of memory is mapped to the DOS
  1170.        memory, so it can be accessed directly.
  1171.      */
  1172.  
  1173.     memcpy (((void *) ((unsigned long) new_handler.x.seg << 4)),
  1174.         RM_handler,
  1175.         RM_ISR_TOTAL_SIZE);
  1176.  
  1177.     if ((DOSX_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES, new_handler.fp))
  1178.     != DOS_SUCCESS)
  1179.     {
  1180.       DOSX_free_DOS_block (new_handler.x.seg);
  1181.       fflush (stdout);
  1182.       free (RM_handler);
  1183.       errno = EFAULT;
  1184.       return (DOS_FAILURE);
  1185.     }
  1186.     DOSX_RM_segment = new_handler.x.seg;
  1187.  
  1188. #endif /* 0 */
  1189.  
  1190.     scheme_RM_vector = RM_handler;
  1191.   }
  1192.  
  1193. #endif /* DOSX_PM_HANDLER_UNTOUCHED */
  1194. #endif /* DOSX_USE_INT_INTERCEPT */
  1195.   return (DOS_SUCCESS);
  1196. }
  1197.  
  1198. static int
  1199. DOSX_restore_kbd_hook (void)
  1200. {
  1201.   if (!(install_kbd_hook_p (DOSX_env_var)))
  1202.     return (DOS_FAILURE);
  1203.  
  1204. #ifdef DOSX_USE_INT_INTERCEPT
  1205.  
  1206.   (void) int_restore (DOS_INTVECT_SYSTEM_SERVICES);
  1207.   scheme_PM_vector = ((void *) NULL);
  1208.   
  1209. #else /* not DOSX_USE_INT_INTERCEPT */
  1210. #ifndef DOSX_PM_HANDLER_UNTOUCHED
  1211.  
  1212.   DOSX_restore_vector (DOS_INTVECT_SYSTEM_SERVICES,
  1213.                old_PM_vector_eip, 
  1214.                old_PM_vector_cs,
  1215.                old_RM_vector.fp);
  1216.  
  1217.   free (scheme_PM_vector);
  1218.   scheme_PM_vector = ((void *) NULL);
  1219.  
  1220. #endif /* DOSX_PM_HANDLER_UNTOUCHED */
  1221.  
  1222. #ifdef DOSX_RM_HANDLER_REAL
  1223.  
  1224.   if ((DOSX_RM_setvector (DOS_INTVECT_SYSTEM_SERVICES,
  1225.               ((unsigned) old_RM_vector)))
  1226.       != DOS_SUCCESS)
  1227.     return (DOS_FAILURE);
  1228.  
  1229. #if 1
  1230.  
  1231.   if ((DOSX_free_DOS_block (DOSX_RM_segment)) != DOS_SUCCESS)
  1232.     return (DOS_FAILURE);
  1233.   DOSX_RM_segment = 0;
  1234.  
  1235. #endif /* 1 */
  1236.  
  1237.   free (scheme_RM_vector);
  1238.   scheme_RM_vector = ((void *) NULL);
  1239.  
  1240. #endif /* DOSX_RM_HANDLER_REAL */
  1241. #endif /* DOSX_USE_INT_INTERCEPT */
  1242.   return (DOS_SUCCESS);
  1243. }
  1244.  
  1245. int
  1246. dos_install_kbd_hook (void)
  1247. {
  1248.   if (scheme_PM_vector != ((void *) NULL))
  1249.   {
  1250.     errno = ELOOP;
  1251.     return (DOS_FAILURE);
  1252.   }
  1253.   if (under_DPMI_p ())
  1254.     return (DPMI_install_kbd_hook ());
  1255.   else
  1256.     return (DOSX_install_kbd_hook ());
  1257. }
  1258.  
  1259. int
  1260. dos_restore_kbd_hook (void)
  1261. {
  1262.   if ((scheme_PM_vector == ((void *) NULL))
  1263.       && (scheme_RM_vector == ((void *) NULL)))
  1264.     return (DOS_SUCCESS);
  1265.   else if (!under_DPMI_p ())
  1266.   {
  1267.     if ((DOSX_restore_kbd_hook ()) != DOS_SUCCESS)
  1268.       return (DOS_FAILURE);
  1269.   }
  1270.   else if ((DPMI_restore_kbd_hook ()) != DOS_SUCCESS)
  1271.     return (DOS_FAILURE);
  1272.  
  1273.   if (scheme_PM_vector != ((void *) NULL))
  1274.   {
  1275.     free (scheme_PM_vector);
  1276.     scheme_PM_vector = ((void *) NULL);
  1277.   }
  1278.   if (scheme_RM_vector != ((void *) NULL))
  1279.   {
  1280.     free (scheme_RM_vector);
  1281.     scheme_RM_vector = ((void *) NULL);
  1282.   }
  1283.   return (DOS_SUCCESS);
  1284. }
  1285.  
  1286. unsigned char
  1287. dos_set_kbd_modifier_mask (unsigned char new_mask)
  1288. {
  1289.   unsigned char old_mask = modifier_mask;
  1290.  
  1291.   modifier_mask = new_mask;
  1292.  
  1293. #ifdef DPMI_RM_HANDLER_REAL
  1294.  
  1295.   if (DPMI_RM_selector != 0)
  1296.     farcpy (RM_ISR_MASK_OFFSET, DPMI_RM_selector, 
  1297.         ((unsigned) (& modifier_mask)), (getDS ()),
  1298.         1);
  1299.  
  1300. #endif /* DPMI_RM_HANDLER_REAL */
  1301.  
  1302. #ifdef DOSX_RM_HANDLER_REAL
  1303.  
  1304.   if (DOSX_RM_segment != 0)
  1305.     (* ((unsigned char *)
  1306.     ((((unsigned long) DOSX_RM_segment) << 4) + RM_ISR_MASK_OFFSET)))
  1307.       = modifier_mask;
  1308.  
  1309. #endif /* DOSX_RM_HANDLER_REAL */
  1310.  
  1311.   return (old_mask);
  1312. }
  1313.  
  1314. extern int EXFUN (dos_set_kbd_translation,
  1315.           (unsigned, unsigned, unsigned char));
  1316.  
  1317. #ifndef PADDED_PATTERN_SIZE
  1318. #  define PADDED_PATTERN_SIZE 0
  1319. #endif
  1320.  
  1321. #ifndef RM_ISR_TABLE_SIZE
  1322. #  define RM_ISR_TABLE_SIZE 0
  1323. #endif
  1324.  
  1325. int
  1326. dos_set_kbd_translation (unsigned shift_p,
  1327.              unsigned scan_code,
  1328.              unsigned char new)
  1329. {
  1330.   unsigned char old;
  1331.   unsigned char * table;
  1332.   unsigned offset;
  1333.  
  1334.   if (scan_code >= (sizeof (shifted_scan_code_to_ascii)))
  1335.     return (-1);
  1336.  
  1337.   if (shift_p != 0)
  1338.   {
  1339.     table = &shifted_scan_code_to_ascii[0];
  1340.     offset = PADDED_PATTERN_SIZE;
  1341.   }
  1342.   else
  1343.   {
  1344.     table = &unshifted_scan_code_to_ascii[0];
  1345.     offset = (PADDED_PATTERN_SIZE + RM_ISR_TABLE_SIZE);
  1346.   }
  1347.   old = table[scan_code];
  1348.   table[scan_code] = new;
  1349.                    
  1350.  
  1351. #ifdef DPMI_RM_HANDLER_REAL
  1352.  
  1353.   if (DPMI_RM_selector != 0)
  1354.     farcpy ((offset + scan_code),
  1355.         DPMI_RM_selector,
  1356.         ((unsigned) (& table[scan_code])),
  1357.         (getDS ()),
  1358.         1);
  1359.  
  1360. #endif /* DPMI_RM_HANDLER_REAL */
  1361.  
  1362. #ifdef DOSX_RM_HANDLER_REAL
  1363.  
  1364.   if (DOSX_RM_segment != 0)
  1365.     (* ((unsigned char *)
  1366.     ((((unsigned long) DOSX_RM_segment) << 4) + offset)))
  1367.       = new;
  1368.  
  1369. #endif /* DOSX_RM_HANDLER_REAL */
  1370.  
  1371.   return (old);
  1372. }
  1373.